// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Diagnostics.Contracts; using System.Text; using System.Xml.Serialization; namespace LargoCommon.Music { /// Melodic interval. /// MelodicInterval represents one interval, i.e. relation of two pitches. /// Includes characteristics like minimal track Value or easy sing Value used for /// optimization of melodies. /// [Serializable] [XmlRoot] public sealed class MelodicInterval : MusicalInterval { #region Fields /// /// Musical pitch1. /// private readonly MusicalPitch pitch1; /// /// Musical pitch2. /// private readonly MusicalPitch pitch2; /// Interval musical properties. private float? minTrack, easySing; #endregion #region Constructors /// Initializes a new instance of the MelodicInterval class. /// Harmonic system. /// First musical pitch. /// Second musical pitch. public MelodicInterval(HarmonicSystem harmonicSystem, MusicalPitch givenPitch1, MusicalPitch givenPitch2) : base(harmonicSystem, givenPitch1, givenPitch2) { Contract.Requires(harmonicSystem != null); this.pitch1 = givenPitch1; this.pitch2 = givenPitch2; this.minTrack = null; this.easySing = null; } /// Initializes a new instance of the MelodicInterval class. Serializable. public MelodicInterval() { } /// Initializes a new instance of the MelodicInterval class. /// Harmonic system. /// Fist element of system. /// Second element of system. public MelodicInterval(HarmonicSystem harmonicSystem, byte elementFrom, byte elementTo) : base(harmonicSystem, elementFrom, elementTo) { Contract.Requires(harmonicSystem != null); } /// Initializes a new instance of the MelodicInterval class. /// Harmonic system. /// First melodic tone. /// Second melodic tone. public MelodicInterval(HarmonicSystem harmonicSystem, MusicalTone tone1, MusicalTone tone2) : base(harmonicSystem, tone1, tone2) { Contract.Requires(harmonicSystem != null); Contract.Requires(tone1 != null); Contract.Requires(tone2 != null); } #endregion #region Properties /// Gets the first pitch of the interval. /// Property description. public MusicalPitch Pitch1 { get { Contract.Ensures(Contract.Result() != null); if (this.pitch1 == null) { throw new InvalidOperationException("Pitch is null."); } return this.pitch1; } } /// Gets the second pitch of the interval. /// Property description. public MusicalPitch Pitch2 { get { Contract.Ensures(Contract.Result() != null); if (this.pitch2 == null) { throw new InvalidOperationException("Pitch is null."); } return this.pitch2; } } /// Gets the easy-sing value. /// Evaluates how easy it is to sing given interval. public float EasySing { get { if (this.easySing != null) { return (float)this.easySing; } var harmonicSystem = this.Pitch2.HarmonicSystem; //// int sysLength = this.Pitch1.DistanceFrom(this.Pitch2); var frmLength = this.Pitch1.FormalDistanceFrom(this.Pitch2); this.easySing = frmLength < harmonicSystem.Median ? 1.0f : -1.0f; //// frmLength == 0 || (sysLength < harmonicSystem.Order && Math.Abs(FormalContinuity) > DefaultValue.Fifty) //// || (sysLength < harmonicSystem.Order / 2 && FormalImpulse > DefaultValue.Fifty) ? 1.0f : -1.0f; return (float)this.easySing; } } /// Gets the minimum-track value. /// Is higher for smaller changes in the musical pitch.. public float MinimumMotion { //// float impulseValue = (fDist == 0) ? -1 : r; get { if (this.minTrack != null) { return (float)this.minTrack; } var harmonicSystem = this.Pitch2.HarmonicSystem; float distance = this.Pitch2.DistanceFrom(this.Pitch1); var r = distance / harmonicSystem.Order; //// harmonicSystem.Order != 0 ? distance / harmonicSystem.Order : 0; this.minTrack = r; return (float)this.minTrack; } } #endregion #region String representation /// String representation - not used, so marked as static. /// Returns value. public override string ToString() { var s = new StringBuilder(); s.Append(this.Pitch1); s.Append(this.Pitch2); return s.ToString(); } #endregion } }